#!/bin/sh /etc/rc.common
# Copyright (C) 2006 Michele Favara Pedarsi <mik.fp@commentaria.com>
# derivative work from the good folks at freifunk.net
# licensed under GPL (any version at any time)
#
# NOTE: ff_* vars are freifunk features; 
#       as I cannot guarrantee to mantain the code
#       I left the ff_* vars as they are, to simplify
#	the porting of future features from Freifunk.
#	Please note also that I don't want to steal the glory
#	at the Freifunk community: they are the good guys that made
#	all this possible. I just found their development quite messy
#	and almost impossible for me to contribute to 
#       (heavvy customized C code, docs in german, no answers to my emails, etc).
#	So I just ripped their features and imported into the standard
#	OpenWrt distribution (using openwrt packages only). In this way it will be easier to
#	develop it further and to integrate into the standard OpenWrt Webif.

START=50


set_network() {
	# TODO: autoselect interfaces to enable olsr on
	OLSRDEV=wl0
	OLSRDEVLIST=wl0
}

write_config() {
	test -d /var/ || ln -s /tmp /var

	LANNET=$(ipcalc $(uci get network.lan.ipaddr) $(uci get network.lan.netmask) | grep NETWORK | cut -d= -f2)
	LANMSK=$(uci get network.lan.netmask)
	
	HNA4=$(uci get olsr.general.ff_hna4)
	DMZS=$(uci get mesh.network.ff_dmz)
	IFS=\;
	for DMZ in $DMZS; do
		SRCIP=${DMZ%[:,]*}
		if [ -n "$HNA4" ]; then
			HNA4="$HNA4;$SRCIP/32"
		else
			HNA4="$SRCIP/32"
		fi
	done
	unset IFS
	
	SPEED=$(uci get olsr.general.ff_olsrspeed)
	test -z "$SPEED" && SPEED=6
	
	FEYE=$(uci get olsr.options.ff_fisheye)
	if [ "0" != "$FEYE" ];then
		TCINT=$(( 1 + 1 * SPEED / 2 ))
		TCVAL=3
		COVER=7
		FEYE=1
	else
		TCINT=$(( 2 * SPEED ))
		TCVAL=1
		COVER=3
		FEYE=0
	fi
	REYE="LinkQualityDijkstraLimit 0 $(( 3 * SPEED / 2 )).0"
	if [ "0" = "$(uci get olsr.options.ff_rfisheye)" ];then
		REYE=
	fi
	
	cat>/var/olsrd.conf<<EOM
DebugLevel	0
IpVersion	4
AllowNoInt	yes
TcRedundancy	2
MprCoverage	$COVER
LinkQualityFishEye	$FEYE
LinkQualityWinSize	100
$REYE
EOM

	if [ "$(uci get olsr.plugins.ff_dyngw)" != "0" ]; then
		cat>>/var/olsrd.conf<<EOM
LoadPlugin "olsrd_dyn_gw.so.0.4"
{
EOM
		for ping in $(uci get olsr.plugins.ff_ping); do
			echo "PlParam	\"Ping\"	\"$ping\"" >>/var/olsrd.conf
		done
		echo "}">>/var/olsrd.conf
	fi
	
	MESH_HOSTNAME=$(uci get mesh.network.hostname)
	MESH_DOMAIN=$(uci get mesh.network.domain)
	if [ -n "$MESH_HOSTNAME" ] && [ "$(uci get olsr.plugins.ff_nameservice)" != "0" ]; then
		cat>>/var/olsrd.conf<<EOM
LoadPlugin "olsrd_nameservice.so.0.2"
{
	PlParam "name" "$MESH_HOSTNAME"
	PlParam "hosts-file" "/var/hosts.olsrd"
	PlParam "suffix" ".$MESH_DOMAIN"
EOM

		SRV="$(uci get olsr.plugins.ff_service)"
		if [ -n "$SRV" ]; then
			IFS=\;
			for ENT in $SRV; do
				echo "  PlParam \"service\"     \"$ENT\"">>/var/olsrd.conf
			done
			unset IFS
		fi
		echo "}">>/var/olsrd.conf
	fi
	
	# TODO: compile txtinfo instead of httpinfo
	if [ "$(uci get olsr.plugins.ff_httpinfo)" != "0" ]; then
		HTTPINFO_PARA="PlParam \"Net\" \"$LANNET $LANMSK\""
		cat>>/var/olsrd.conf<<EOM
LoadPlugin "olsrd_httpinfo.so.0.1"
{
	PlParam	"port"	"8080"
	PlParam	"Host"	"127.0.0.1"
	$HTTPINFO_PARA
}
EOM
	fi
	
	# TODO: compile bmf
	# TODO: add manual hna4 entries
	
	# TODO: Allow Ipc from other hosts/nets
	IPC_PARA="Net $LANNET $LANMSK"
	cat>>/var/olsrd.conf<<EOM
IpcConnect
{
	MaxConnections	1
	Host	127.0.0.1
	$IPC_PARA
}
EOM

	ff_qos=2
	ff_qoslev=$(uci get olsr.general.ff_qoslev)
	case "$ff_qoslev" in
		0|1|2)
			ff_qos=$ff_qoslev
		;;
	esac
	echo "LinkQualityLevel $ff_qos">>/var/olsrd.conf
	if [ -z "$ff_qos" ] || [ "$ff_qos" = "0" ]; then
		ff_hyst=$(uci get olsr.standard.ff_hyst)
		test -n "$ff_hyst" && echo "UseHysteresis $ff_hyst">>/var/olsrd.conf
		ff_scale=$(uci get olsr.standard.ff_scale)
		test -n "$ff_scale" && echo "HystScaling $ff_scale">>/var/olsrd.conf
		ff_thrh=$(uci get olsr.standard.ff_thrh)
		test -n "$ff_thrh" && echo "HystThrHigh $ff_thrh">>/var/olsrd.conf
		ff_thrl=$(uci get olsr.standard.ff_thrl)
		test -n "$ff_thrl" && echo "HystThrLow $ff_thrl">>/var/olsrd.conf
	else
		echo "UseHysteresis no">>/var/olsrd.conf
	fi
	
	ff_lqmult=
	LQMS=$(uci get olsr.etx.ff_lqmult)
	IFS=\;
	for LQM in $LQMS; do
		SRCIP=${LQM%[:,]*}
		LQVAL=${LQM#*[:,]}
		if [ -n "$SRCIP" ] && [ -n "$LQVAL" ]; then
			ff_lqmults="$ff_lqmults
	LinkQualityMult $SRCIP $LQVAL"
		fi
	done
	unset IFS
	
	ff_will=$(uci get olsr.general.ff_will)
	test -n "$ff_will" && echo "Willingness $ff_will">>/var/olsrd.conf
	
	ff_ip4broad=$(uci get olsr.general.ff_ip4broad)
	test -n "$ff_ip4broad" && ff_ip4broad="Ip4Broadcast $(uci get olsr.general.ff_ip4broad)"
	
	for DEV in $OLSRDEVLIST; do
		cat>>/var/olsrd.conf<<EOM
Interface "$DEV"
{
	HelloInterval		$(( 1 * SPEED )).0
	HelloValidityTime	$(( 18 * SPEED )).0
	TcInterval		$TCINT.0
	TcValidityTime		$(( 18 * SPEED * TCVAL )).0
	MidInterval		$(( 3 * SPEED )).0
	MidValidityTime		$(( 18 * SPEED * TCVAL )).0
	HnaInterval		$(( 3 * SPEED )).0
	HnaValidityTime		$(( 18 * SPEED )).0
	$ff_ip4broad
	$ff_lqmults
	$(test -f /etc/local.olsrd.conf.$DEV && cat /etc/local.olsrd.conf.$DEV)
}
EOM
	done
	for i in /etc/local.olsrd.conf /etc/local.olsrd.conf-*; do
		test -f $i && cat>>/var/olsrd.conf<$i
	done
}

start() {
	[ ".$(uci get mesh.general.enable)" == ".1" ] || exit
	test -z "$(l=$(grep : /proc/net/wireless);l=${l%:*};echo ${l##* })" && exit
	set_network
	write_config
	echo 0 >/proc/sys/net/ipv4/conf/all/send_redirects
	DEBUG_LEVEL=$(uci get olsr.general.ff_debug)
	olsrd -d ${DEBUG_LEVEL:-0}
}

stop() {
	killall olsrd >/dev/null 2>&1
	/usr/sbin/olsrd.clearroutes
}

